package br.com.locanet.view;

import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import br.com.locanet.bean.IEntity;
import br.com.locanet.bean.impl.Cliente;
import br.com.locanet.bean.impl.Funcionario;
import br.com.locanet.bean.impl.Pessoa;
import br.com.locanet.dao.GenericJPADAO;
import br.com.locanet.service.AbstractEntityService;
import br.com.locanet.util.UtilReflection;

public abstract class AbstractManagedBean<ENTITY extends IEntity, SERVICE extends AbstractEntityService<ENTITY, ? extends GenericJPADAO<ENTITY>>>{
	public static final String SESSION_FUNCIONARIO = "funcionario";
	public static final String SESSION_CLIENTE = "cliente";
	
	public String INSERT = getEntityClassName() + "_INSERT";
	public String INSERT_SUCCESS = getEntityClassName() + "_INSERT_SUCCESS";
	public String UPDATE = getEntityClassName() + "_UPDATE";
	public String UPDATE_SUCCESS = getEntityClassName() + "_UPDATE_SUCCESS";
	public String REMOVE = getEntityClassName() + "_REMOVE";
	public String SEARCH = getEntityClassName() + "_SEARCH";
	
    private ENTITY entity;
    private List<ENTITY> entities;
    private SERVICE entityService;
    
    protected String getEntityClassName(){
    	try {
			return UtilReflection.getGenericClassType(getClass()).getSimpleName().toUpperCase();
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
    }
	
	protected void addMessage(String message){
        addMessage(null, message);
    }

    protected void addMessage(String clientId, String message){
        getFacesContext().addMessage(clientId, new FacesMessage(message));
    }

    protected void addErrorMessage(String error){
        addMessage("errorMessage", error);
    }

    protected void addAlertMessage(String alert){
        addMessage("alertMessage", alert);
    }

    protected void addSuccessMessage(String success){
        addMessage("successMessage", success);
    }

    protected HttpServletRequest getRequest(){
        return (HttpServletRequest) getFacesContext().getExternalContext().getRequest();
    }

    protected HttpSession getSession(){
        return (HttpSession) getFacesContext().getExternalContext().getSession(false);
    }

    protected FacesContext getFacesContext(){
        return FacesContext.getCurrentInstance();
    }
    
    public String openInsert(){
    	return INSERT;
    }
    
    public String openUpdate(){
    	setEntity(getEntityService().selectById(getEntity()));
    	return UPDATE;
    }

	@SuppressWarnings("unchecked")
	public ENTITY getEntity() {
		if (entity==null){
			try{
				entity = ((ENTITY) UtilReflection.getGenericClassType(getClass()).newInstance());
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		return entity;
	}

	public void setEntity(ENTITY entity) {
		this.entity = entity;
	}

	public List<ENTITY> getEntities() {
		if (entities==null){
			try {
				search();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return entities;
	}

	public void setEntities(List<ENTITY> entities) {
		this.entities = entities;
	}

	@SuppressWarnings("unchecked")
	protected SERVICE getEntityService() {
		if (entityService==null){
			try {
				setEntityService(((SERVICE) UtilReflection.getGenericClassType(getClass(),1).newInstance()));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return entityService;
	}

	protected void setEntityService(SERVICE entityService) {
		this.entityService = entityService;
	}
	
	public String insert() throws Exception{
		setEntity(getEntityService().insert(getEntity()));
		setEntities(null);
		return INSERT_SUCCESS;
	}
	public String update() throws Exception{
		setEntity(getEntityService().update(getEntity()));
		setEntities(null);
		search();
		return UPDATE_SUCCESS;
	}
	public String remove() throws Exception{
		getEntityService().delete(entity);
		setEntities(null);
		return REMOVE;
	}
	public String search() throws Exception{
		setEntities(getEntityService().select(getEntity()));
		return SEARCH;
	}
	
	public boolean isCliente() {
		return getRequest().getSession().getAttribute(SESSION_CLIENTE)!=null
			&&(getRequest().getSession().getAttribute(SESSION_CLIENTE) instanceof Cliente);
	}

	public boolean isFuncionario(){
		return getRequest().getSession().getAttribute(SESSION_FUNCIONARIO)!=null
			&&(getRequest().getSession().getAttribute(SESSION_FUNCIONARIO) instanceof Funcionario);
	}
	
	public Cliente getClienteInSession(){
		return (Cliente) getSession().getAttribute(SESSION_CLIENTE);
	}
	
	public Funcionario getFuncionarioInSession(){
		return (Funcionario) getSession().getAttribute(SESSION_FUNCIONARIO);
	}
	
	public void setPessoaInSession(Pessoa entity){
		if (entity instanceof Cliente){
			getSession().setAttribute(SESSION_CLIENTE, entity);
		}else if (entity instanceof Funcionario){
			getSession().setAttribute(SESSION_FUNCIONARIO, entity);
		}
	}
	
	public Pessoa getPessoaInSession(){
		if (isFuncionario()){
			return getFuncionarioInSession();
		}else if (isCliente()){
			return getClienteInSession();
		}
		return null;
	}
}
